package com.huanletao.quartz.schedule;

import com.huanletao.quartz.entity.JobDetails;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * QuartzScheduleUtils 定时任务核心操作类:
 * 1. 添加定时任务，
 * 2. 删除定时任务，
 * 3. 暂停任务，
 * 4. 触发任务；
 * </p>
 *
 * @package: com.huanletao.quartz
 * @description:
 * @className: HelloJob
 * @author: @nncskj admin
 * @date: Created in 2022/5/31
 * @copyright: Copyright (c) 2022/5/31
 * @version: V2.0
 */
public class DefaultQuartzSchedule implements QuartzSchedule {

    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultQuartzSchedule.class);

    private Scheduler scheduler;

    public Scheduler getScheduler() {
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public DefaultQuartzSchedule() {
    }

    /**
     * 添加定时任务
     *
     * @param jobDetails JobDetails
     * @throws SchedulerException
     */
    public void addJob(JobDetails jobDetails) throws SchedulerException {
        addQuartzJob(jobDetails);
    }

    /**
     * 触发一次,
     *
     * @param jobDetails JobDetails
     * @throws SchedulerException
     */
    public void trigger(JobDetails jobDetails) throws SchedulerException {
        scheduler.triggerJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
    }

    /**
     * 暂停一个job;
     *
     * @param jobDetails JobDetails
     * @throws SchedulerException
     */
    @Override
    public void pauseJob(JobDetails jobDetails) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
    }

    /**
     * 恢复一个job
     *
     * @param jobDetails JobDetails
     * @throws SchedulerException
     */
    @Override
    public void resumeJob(JobDetails jobDetails) throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
    }

    /**
     * 启动所有任务
     *
     * @throws SchedulerException
     */
    @Override
    public void startJobs() throws SchedulerException {
        scheduler.start();
        LOGGER.debug("启动所有任务");
    }

    /**
     * 关闭所有定时任务
     *
     * @throws SchedulerException
     */
    @Override
    public void shutdownJobs() throws SchedulerException {
        if (!scheduler.isShutdown()) {
            scheduler.shutdown();
            LOGGER.debug("关闭所有任务");
        }
    }


    /**
     * @param jobDetails JobDetails
     * @throws SchedulerException
     * @Description: 修改一个任务的触发时间(使用默认的任务组名 ， 触发器名 ， 触发器组名)
     */
    public void modifyJobTime(JobDetails jobDetails) throws SchedulerException {
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(
                TriggerKey.triggerKey(jobDetails.getJobName(), jobDetails.getGroupName()));
        if (trigger == null) {
            return;
        }
        String oldTime = trigger.getCronExpression();
        if (!oldTime.equalsIgnoreCase(jobDetails.getCron())) {
            JobDetail jobDetail = scheduler.getJobDetail(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
            removeJob(jobDetails);
            addJob(jobDetails);
            LOGGER.debug("修改任务:{},{}", jobDetail);
        }
    }

    /**
     * @param jobDetails
     * @throws SchedulerException
     */
    @Override
    public void addQuartzJob(JobDetails jobDetails) throws SchedulerException {

        JobDetail jobDetail = JobBuilder.newJob(jobDetails.getExecuteJobClass())
                .withIdentity(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName())).build();

        CronScheduleBuilder cb = CronScheduleBuilder.cronSchedule(jobDetails.getCron());
        CronScheduleBuilder scheduleBuilder = handleCronScheduleMisfirePolicy(jobDetails, cb);

        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(TriggerKey.triggerKey(jobDetails.getJobName(), jobDetails.getGroupName()))
                .withSchedule(scheduleBuilder)
                .build();

        //设置参数传递;
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        jobDataMap.put("jobDetails", jobDetails);
        scheduler.scheduleJob(jobDetail, trigger);
        LOGGER.info("添加任务:{},", jobDetails);
        if (jobDetails.getMisfirePolicy() == 1) {
            scheduler.triggerJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
        }
//        // 启动
//        if (!scheduler.isShutdown()) {
//            scheduler.start();
//        }
    }

    /**
     * 设置定时任务策略
     */
    public static CronScheduleBuilder handleCronScheduleMisfirePolicy(JobDetails job, CronScheduleBuilder cb)
            throws RuntimeException {
        switch (job.getMisfirePolicy()) {
            case 0:
                return cb;
            case 1:
                return cb.withMisfireHandlingInstructionIgnoreMisfires();
            case 2:
                return cb.withMisfireHandlingInstructionFireAndProceed();
            case 3:
                return cb.withMisfireHandlingInstructionDoNothing();
            default:
                throw new RuntimeException("The task misfire policy '" + job.getMisfirePolicy()
                        + "' cannot be used in cron schedule tasks");
        }
    }

    @Override
    public void removeQuartzJob(JobDetails jobDetails) throws SchedulerException {
        removeJob(jobDetails);
    }

    @Override
    public void triggerJob(JobDetails jobDetails) throws SchedulerException {
        trigger(jobDetails);
    }

    /**
     * 移除任务；
     *
     * @param jobDetails
     * @throws SchedulerException
     */
    public void removeJob(JobDetails jobDetails) throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobDetails.getJobName(), jobDetails.getGroupName()));
        scheduler.deleteJob(JobKey.jobKey(jobDetails.getJobName(), jobDetails.getGroupName()));
        LOGGER.debug("移除任务:{},{}", jobDetails.getJobName(), jobDetails.getGroupName());
    }

}